package com.tyfspring.beans.factory;

import com.tyfspring.beans.DisposableBean;
import com.tyfspring.beans.exception.BeansException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description 管理单例Bean实例的默认实现类,用于在容器启动时注册、缓存和获取单例Bean实例
 * @Author shallow
 * @Date 2023/3/26 14:39
 */

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry{

    protected static final Object NULL_OBJECT = new Object();

    //一级缓存,用于缓存已经完成创建和初始化的单例Bean实例
    private Map<String,Object> singletonObjects = new HashMap<>();

    //二级缓存,缓存正在创建中的单例Bean实例
    private Map<String,Object> earlySingletonObjects = new HashMap<>();

    //三级缓存，Bean的工厂对象
    private Map<String, ObjectFactory> singletonFactories = new HashMap<>();

    private final Map<String, DisposableBean> disposableBeans = new HashMap<>();


    @Override
    public Object getSingleton(String beanName) {
        //先从一级缓存中获取单例，若没有，去二级缓存
        Object singletonObject = singletonObjects.get(beanName);
        if (singletonObject == null) {
            singletonObject = earlySingletonObjects.get(beanName);
            //若还没有，去三级缓存中寻找
            if (singletonObject == null) {
                ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
                if (singletonFactory!=null) {
                    //三级缓存找到后，通过getObject方法，获取单例
                    singletonObject = singletonFactory.getObject();
                    //从三级缓存放进二级缓存，清除三级缓存中的对象
                    earlySingletonObjects.put(beanName,singletonObject);
                    singletonFactories.remove(beanName);

                }
            }
        }
        return singletonObject;
    }

    @Override
    public void registerSingleton(String beanName, Object singletonObject) {
        //一级缓存添加单例，清除二，三级缓存对应对象
        singletonObjects.put(beanName,singletonObject);
        earlySingletonObjects.remove(beanName);
        singletonFactories.remove(beanName);
    }

    public void registerDisposableBean(String beanName, DisposableBean bean) {
        disposableBeans.put(beanName, bean);
    }

    /**
     * 删除disposableBeans中的对象
     */
    public void destroySingletons() {
        ArrayList<String> beanNames = new ArrayList<>(disposableBeans.keySet());
        for (String beanName : beanNames) {
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
            }
        }
    }
}
